#!/usr/bin/env python
# -*-coding:utf-8 -*-

"""
1. 理解可迭代对象（Iterable）、迭代器（Iterator）、迭代（Iteration） 三个术语

迭代：用简单的话讲，它就是从某个地方（比如一个列表）取出一个元素的过程。当我们使用一个循环来遍历某个东西时，这个过程本身就叫迭代

生成器(Generators)：生成器也是一种迭代器，但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中，而是在运行时生成值。
通过生成器来创建迭代器是一种更简洁的方式。生成器是一种使用简单的语法创建迭代器的工具，它通过函数加上yield语句来实现。
"""

# 定义一个可迭代对象
import sys


class Student(object):
    """
    1. 可迭代对象就是能(able)提供迭代器的任意对象
    """

    def __iter__(self):
        print("可迭代对象包含要素一：包含__iter__ 方法\n")
        self.a = 1
        return self

    # 支持下标索引
    def __getitem__(self, item):
        print("可迭代对象包含要素二：包含__getitem__ 方法")

    def __next__(self):
        print("任意对象包含__next__方法，那么它就是一个迭代器(iterator)")
        x = self.a
        self.a += 1
        return x

    def create_iterator(self):
        print("\ncreate_iterator")
        list = [1, 2, 3, 4]
        it = iter(list)  # 创建迭代器对象
        print(next(it))  # 输出迭代器的下一个元素
        print(next(it))

    # 迭代器对象可以使用常规for语句进行遍历：
    def create_iterator_two(self):
        print("\ncreate_iterator_two")
        list = [1, 2, 3, 4]
        it = iter(list)  # 创建迭代器对象
        for x in it:
            print(x, end=" ")

    # 迭代器对象可以使用next()函数进行遍历：
    def create_iterator_three(self):
        print("\ncreate_iterator_three")
        list = [1, 2, 3, 4]
        it = iter(list)  # 创建迭代器对象
        while True:
            try:
                print(next(it), end=" ")
            except StopIteration:  # 其实for 循环遍历就是捕获了 StopIteration后进行了停止
                sys.exit()

    # 生成器二
    def generator_squares(self, start, end):
        print("\n生成器二，通过生成器可以更简洁的创建迭代器: generator_squares")
        for value in range(start, end + 1):
            yield value ** 2

    # 生成器一，通过生成器可以更简洁的创建迭代器
    def generator_function(self):
        print("\n生成器一，通过生成器可以更简洁的创建迭代器: generator_function")
        for i in range(5):
            yield i


s = Student()
# 创建自定义迭代器,测试一下将该行代码挪到77行时会正常执行嘛？ 为什么
myiter = iter(s)  # 会执行 __iter__ 方法
print(next(myiter))  # 执行自定义的迭代器 __next()__ 方法
print(next(myiter))  # 执行自定义的迭代器 __next()__ 方法

# 生成器一
for item in s.generator_function():
    print(item)

# 生成器二
for item in s.generator_squares(2, 5):
    print(item)

s.create_iterator()
s.create_iterator_two()
s.create_iterator_three()

"""
总结：
关于生成器：
谈生成器就无法避免不谈迭代器，是迭代器中的一种，通过生成器可以简洁的创建迭代器

使用了 yield 的函数被称为生成器。
生成器是一个返回迭代器的函数，只能用于迭代操作，更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中，每次遇到 yield 时函数会暂停并保存当前所有的运行信息，返回 yield 的值, 并在下一次执行 next()法时从当前位置继续运行。
"""
